/*
class User{
  constructor(public id:number, public name:string){}
}

type ConstructorParamType1 = ConstructorParameters<typeof User>;

type MyConstructorParameters<T extends abstract new (...args: any[]) => any> = T extends abstract new (...args: infer R) => any ? R : never;

type ConstructorParamType2 = MyConstructorParameters<typeof User>;


type T0 = ConstructorParameters<ErrorConstructor>;
type T1 = ConstructorParameters<FunctionConstructor>;
type T2 = ConstructorParameters<RegExpConstructor>;

// 扩展
class Book{
  title: string;
  content: string;
  constructor(title: string, content:string) { 
    this.title = title;
    this.content = content;
  }
}

class CreateInstance<T extends new (...args: any[]) => any>{ 
  private ClassConstructor:T
  constructor(classConstructor:T) { 
    this.ClassConstructor = classConstructor
  }

  getInstance(...args: ConstructorParameters<T>): InstanceType<T>{
    return new this.ClassConstructor(...args);
  }
}

const instanceCreator = new CreateInstance(Book);
const book = instanceCreator.getInstance("Typescript类型全解","ts类型说明...");

console.log(book);

// let p = {
//   id: 1,
//   name:"jack"
// }

// type P = typeof p;

type U = InstanceType<typeof User>;
// type MyInstanceType<T extends abstract new (...args: any[]) => any> = T extends abstract new (...args: any[]) => infer R ? R : never;
// type InstanceUser = MyInstanceType<typeof User>;
*/

// 在TS中，能不能写构造函数呢？
// 函数是具有二义性的！ES6才有了箭头函数和类的区分
/*
function Person(id:number, name:string, age:number) { 
  this.id = id;
  this.name = name;
  this.age = age;
}

interface Person{
  id: number,
  name: string,
  age:number
}
interface PersonConstructor {
  new(id: number, name: string, age: number): Person;
  readonly prototype: Person;
}
// 通过构造函数类型获取实例类型
type PersonInstance = InstanceType<PersonConstructor>;


const person: PersonInstance = new Person(1, "jack", 20);
*/

// 模拟一个实用的异步场景
// 比如有时候可能第三方库仅仅给我们提供了接口方法(返回Promise)，但是没有提供具体的类型，但是我们又想使用这个类型
interface User{
  id: number;
  firstName: string;
  lastName: string;
  age: number;
}

async function fetchUser():Promise<User> { 
  const data = await fetch("https://www.api.com").then(res => {
    return res.json();
  });
  return data;
}
// 上面的是第三方库的，我们能得到的就是fetchUser接口
type UserFetch = Awaited<ReturnType<typeof fetchUser>>

const user: UserFetch = {
  id: 1,
  firstName: "jack",
  lastName: "chen",
  age:20
}

type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<number>>>; // number
type C = Awaited<Promise<number> | boolean>; // number | boolean
type D = Awaited<number>; // number
type E = Awaited<null>; // null

type MyAwaited<T extends PromiseLike<any>> = Awaited<T>;

// type F = MyAwaited<number>;
// type G = MyAwaited<null>;
// type H = MyAwaited<{id:1}>;

